package com.zmn.oms.business.impl.messageV1.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.api.client.util.Lists;
import com.zmn.biz.engineer.common.constants.DubboConsts;
import com.zmn.biz.engineer.common.dro.device.EngineerDeviceDRO;
import com.zmn.biz.engineer.dubbo.interfaces.device.EngineerDeviceListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.cube.common.utils.StringUtil;
import com.zmn.oms.business.impl.messageV1.ZmnMcsSendUtil;
import com.zmn.oms.business.interfaces.log.OrderLogMessageBService;
import com.zmn.oms.business.interfaces.messageV1.common.MessageSendBaseService;
import com.zmn.oms.model.dto.messageV1.*;
import com.zmn.oms.model.entity.log.OrderMessageLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：发送消息通用类
 *
 * @author yule
 * @date 2020/12/22 22:58
 */
@Service
@Slf4j
public class MessageSendBaseServiceImpl implements MessageSendBaseService {
    @Autowired
    private OrderLogMessageBService orderLogMessageBService;
    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerDeviceListRemoteService engineerDeviceListRemoteService;

    @Override
    public boolean sendTextMessage(Integer ruleId, String phone, Map<String, String> smsMap) {
        SmsMessageDTO smsMessageDTO = SmsMessageDTO.builder()
                .ruleId(ruleId)
                .mobile(phone)
                .params(JSON.toJSONString(smsMap))
                .build();
        return sendTextMessage(smsMessageDTO);
    }

    @Override
    public boolean sendTextMessage(SmsMessageDTO smsMessageDTO) {
        if (!StringUtil.isMobile(smsMessageDTO.getMobile())) {
            log.info("非手机号，短信消息不发送：{}", JSON.toJSONString(smsMessageDTO));
            return false;
        }
        //短信封装
        SmsMessageDIO smsMessageDIO = SmsMessageDIO.builder()
                .mobile(smsMessageDTO.getMobile())
                .params(smsMessageDTO.getParams())
                .build();

        //封装send对象
        SendMscDIO sendMessageDIO = SendMscDIO.builder()
                .orderId(smsMessageDTO.getOrderId())
                .businessId(smsMessageDTO.getOrderId())
                .ruleId(smsMessageDTO.getRuleId())
                .objectId(smsMessageDTO.getMobile())
                .areaId(smsMessageDTO.getCityId())
                .channelId(smsMessageDTO.getChannelId())
                .smsParams(smsMessageDIO)
                .build();
        log.info("短信消息入参数：{}", JSON.toJSONString(sendMessageDIO));
        sendMsg(sendMessageDIO, "短信消息");
        return true;

    }

    @Override
    public String sendWeiXinMessage(WeChatMessageDTO weChatMessage) {
        WeChatMessageDIO smsMessageDIO = WeChatMessageDIO.builder()
                .openId(weChatMessage.getOpenId())
                .thirdAppId(weChatMessage.getThirdAppId())
                .skipType(weChatMessage.getSkipType())
                .params(weChatMessage.getParams())
                .build();

        SendMscDIO sendMessageDIO;

        // 判断小程序设置
        if (StringUtil.isNotBlank(weChatMessage.getMiniProgramOpenId()) && StringUtils.isNotBlank(weChatMessage.getMiniProgramAppId())) {
            WechatMiniMessageDIO wechatMiniMessageDIO = WechatMiniMessageDIO.builder()
                    .touser(weChatMessage.getMiniProgramOpenId())
                    .miniAppId(weChatMessage.getMiniProgramAppId())
                    .params(weChatMessage.getParams())
                    .build();

            sendMessageDIO = SendMscDIO.builder()
                    .orderId(weChatMessage.getOrderId())
                    .ruleId(weChatMessage.getRuleId())
                    .objectId(weChatMessage.getObjectId())
                    .areaId(weChatMessage.getCityId())
                    .channelId(weChatMessage.getChannelId())
                    .weChatMiniParams(wechatMiniMessageDIO)
                    .weChatParams(smsMessageDIO)
                    .delaySecond(weChatMessage.getDelaySecond())
                    .build();
        } else {

            sendMessageDIO = SendMscDIO.builder()
                    .orderId(weChatMessage.getOrderId())
                    .ruleId(weChatMessage.getRuleId())
                    .objectId(weChatMessage.getObjectId())
                    .areaId(weChatMessage.getCityId())
                    .channelId(weChatMessage.getChannelId())
                    .weChatParams(smsMessageDIO)
                    .delaySecond(weChatMessage.getDelaySecond())
                    .build();
        }

        //封装send对象
        log.info("微信消息入参数：{}", JSON.toJSONString(sendMessageDIO));
        return sendMsg(sendMessageDIO, "微信消息");
    }

    @Override
    public boolean sendBaiduMessage(BaiduMessageDTO baiduMessageDTO) {
        BaiduMessageDIO baiduMessageDIO = BaiduMessageDIO.builder()
                .openId(baiduMessageDTO.getOpenId())
                .sceneId(baiduMessageDTO.getSceneId())
                .params(baiduMessageDTO.getParams())
                .page(baiduMessageDTO.getPage())
                .ext(baiduMessageDTO.getExt())
                .build();

        //封装send对象
        SendMscDIO sendMessageDIO = SendMscDIO.builder()
                .orderId(baiduMessageDTO.getOrderId())
                .ruleId(baiduMessageDTO.getRuleId())
                .objectId(baiduMessageDTO.getObjectId())
                .areaId(baiduMessageDTO.getCityId())
                .channelId(baiduMessageDTO.getChannelId())
                .baiduParams(baiduMessageDIO)
                .build();
        sendMsg(sendMessageDIO, "百度消息");
        return true;
    }

    @Override
    public boolean sendAndroidAndIOSMessage(AppMessageDTO appMessageDTO) {
        EngineerDeviceDRO deviceDRO = getMeidByMasterId(appMessageDTO.getMasterId());
        if (Objects.isNull(deviceDRO)) {
            log.info("工程师Id={},获取工程师设备信息失败，终止发送 -----", appMessageDTO.getMasterId());
            return false;
        }

        // 安卓
        AndroidMessageDIO androidMessageDIO = null;
        if (Objects.equals(GlobalConsts.NO, deviceDRO.getMobileSys())) {
            androidMessageDIO = AndroidMessageDIO.builder()
                    .meid(String.valueOf(appMessageDTO.getMasterId()))
                    .plat(appMessageDTO.getPlat())
                    .params(appMessageDTO.getParams())
                    .build();
        }

        // IOS
        IosMessageDIO iosMessageDIO = null;
        if (Objects.equals(GlobalConsts.YES, deviceDRO.getMobileSys())) {
            iosMessageDIO = IosMessageDIO.builder()
                    .meid(String.valueOf(appMessageDTO.getMasterId()))
                    .plat(appMessageDTO.getPlat())
                    .params(appMessageDTO.getParams())
                    .build();
        }

        //封装send对象
        SendMscDIO sendMessageDIO = SendMscDIO.builder()
                .orderId(appMessageDTO.getOrderId())
                .ruleId(appMessageDTO.getRuleId())
                .ruleCode(appMessageDTO.getRuleCode())
                .objectId(String.valueOf(appMessageDTO.getMasterId()))
                .areaId(appMessageDTO.getCityId())
                .channelId(appMessageDTO.getChannelId())
                .androidParams(androidMessageDIO)
                .iosParams(iosMessageDIO)
                .build();
        log.info("androidMessageDIO :{}", JSONObject.toJSONString(androidMessageDIO));
        if (Objects.isNull(androidMessageDIO) && Objects.isNull(iosMessageDIO)) {
            log.info("订单号={}，工程师Id={}，发送ruleId={}，未获取到工程师设备信息 无法满足发送条件 ======", appMessageDTO.getOrderId(), appMessageDTO.getMasterId(), appMessageDTO.getRuleId());
            return false;
        }
        log.info("订单号：{}，工程师Id：{}，发送ruleId：{}", appMessageDTO.getOrderId(), appMessageDTO.getMasterId(), appMessageDTO.getRuleId());
        sendMsg(sendMessageDIO, "工程师App消息");
        return true;
    }

    /**
     * 批量发送App消息
     * @param appMessageDTO
     * @return
     */
    @Override
    public boolean batchSendAndroidAndIOSMessage(AppMessageDTO appMessageDTO) {
        List<EngineerDeviceDRO> deviceDROList = this.getMeIdListByMasterIdList(appMessageDTO.getMasterIdList());
        if (CollectionUtil.isNullOrEmpty(deviceDROList)) {
            log.info("工程师Id集合={},获取工程师设备信息失败，终止发送 -----", appMessageDTO.getMasterIdList());
            return false;
        }

        // 安卓
        List<Integer> androidMasterIdList = Lists.newArrayList();
        // IOS
        List<Integer> iosMasterIdList = Lists.newArrayList();

        deviceDROList.stream().forEach(deviceDRO -> {
            if (Objects.equals(GlobalConsts.NO, deviceDRO.getMobileSys())) {
                androidMasterIdList.add(deviceDRO.getEngineerId());
             }

            if (Objects.equals(GlobalConsts.YES, deviceDRO.getMobileSys())) {
                iosMasterIdList.add(deviceDRO.getEngineerId());
            }
        });

        // 安卓和ios同时只能发一条mq消息 同时存在需要发两条
        if (CollectionUtil.isNotNullOrEmpty(androidMasterIdList)) {
            // 安卓
            AndroidMessageDIO androidMessageDIO = AndroidMessageDIO.builder()
                    .meid(androidMasterIdList.stream().map(String::valueOf).collect(Collectors.joining(",")))
                    .plat(appMessageDTO.getPlat())
                    .params(appMessageDTO.getParams())
                    .build();

            //封装send对象
            androidMasterIdList.addAll(iosMasterIdList);
            SendMscDIO androidMsc = SendMscDIO.builder()
                    .orderId(appMessageDTO.getOrderId())
                    .ruleId(appMessageDTO.getRuleId())
                    .ruleCode(appMessageDTO.getRuleCode())
                    .areaId(appMessageDTO.getCityId())
                    .channelId(appMessageDTO.getChannelId())
                    .androidParams(androidMessageDIO)
                    .build();

            log.info("androidMessageDIO :{}", JSONObject.toJSONString(androidMessageDIO));
            if (Objects.isNull(androidMessageDIO)) {
                log.info("订单号={}，工程师Id={}，发送ruleId={}，未获取到工程师设备信息 无法满足发送条件 ======", appMessageDTO.getOrderId(), appMessageDTO.getMasterId(), appMessageDTO.getRuleId());
                return false;
            }
            log.info("订单号：{}，工程师Id：{}，发送ruleId：{}", appMessageDTO.getOrderId(), androidMasterIdList, appMessageDTO.getRuleId());
            batchSendMsg(androidMsc, "工程师App消息", androidMasterIdList);
        }

        if (CollectionUtil.isNotNullOrEmpty(iosMasterIdList)) {
            // IOS
            IosMessageDIO iosMessageDIO = IosMessageDIO.builder()
                    .meid(iosMasterIdList.stream().map(String::valueOf).collect(Collectors.joining(",")))
                    .plat(appMessageDTO.getPlat())
                    .params(appMessageDTO.getParams())
                    .build();

            SendMscDIO iosMsc = SendMscDIO.builder()
                    .orderId(appMessageDTO.getOrderId())
                    .ruleId(appMessageDTO.getRuleId())
                    .ruleCode(appMessageDTO.getRuleCode())
                    .areaId(appMessageDTO.getCityId())
                    .channelId(appMessageDTO.getChannelId())
                    .iosParams(iosMessageDIO)
                    .build();


            log.info("IosMessageDIO :{}", JSONObject.toJSONString(iosMessageDIO));
            if (Objects.isNull(iosMessageDIO)) {
                log.info("订单号={}，工程师Id={}，发送ruleId={}，未获取到工程师设备信息 无法满足发送条件 ======", appMessageDTO.getOrderId(), appMessageDTO.getMasterId(), appMessageDTO.getRuleId());
                return false;
            }
            log.info("订单号：{}，工程师Id：{}，发送ruleId：{}", appMessageDTO.getOrderId(), androidMasterIdList, appMessageDTO.getRuleId());
            batchSendMsg(iosMsc, "工程师App消息", iosMasterIdList);
        }
        return true;
    }

    /**
     * 保存发送记录
     *
     * @param sendMessage
     * @param tag
     * @return
     */
    private String batchSendMsg(SendMscDIO sendMessage, String tag, List<Integer> masterIdList) {
        // 发送消息
        String serialNumber = ZmnMcsSendUtil.send(sendMessage);

        if (NumberUtil.isNullOrZero(sendMessage.getOrderId())) {
            return serialNumber;
        }

        try {
            Long orderId = Optional.ofNullable(sendMessage.getOrderId()).orElse(0L);
            // 消息app轨迹用于区分订单消息
            if (Objects.nonNull(sendMessage.getAndroidParams()) || Objects.nonNull(sendMessage.getIosParams())) {
                orderId = orderId + 111;
            }
            //-----保存发送记录
            if (CollectionUtil.isNullOrEmpty(masterIdList)) {
                return serialNumber;
            }

            for (Integer masterId : masterIdList) {
                OrderMessageLog orderMessageLog = new OrderMessageLog();
                orderMessageLog.setOrderId(orderId);
                orderMessageLog.setSendUserId(masterId.longValue());
                orderMessageLog.setGroupId(sendMessage.getRuleId());
                orderMessageLog.setTagName(tag);
                orderMessageLog.setContentIn(JSON.toJSONString(sendMessage));
                orderMessageLog.setContentOut(Optional.ofNullable(serialNumber).orElse("失败"));
                orderMessageLog.setCreateTime(new Date());
                orderLogMessageBService.save(orderMessageLog);
            }

        } catch (Exception ex) {
            log.error(String.format("订单号%s，保存%s发送记录接口异常了:%s", sendMessage.getOrderId(), tag, ex.getMessage()), ex);
            return serialNumber;
        }
        return serialNumber;
    }

    /**
     * 保存发送记录
     *
     * @param sendMessage
     * @param tag
     * @return
     */
    private String sendMsg(SendMscDIO sendMessage, String tag) {
        // 发送消息
        String serialNumber = ZmnMcsSendUtil.send(sendMessage);

        if (NumberUtil.isNullOrZero(sendMessage.getOrderId())) {
            return serialNumber;
        }
        try {
            Long orderId = Optional.ofNullable(sendMessage.getOrderId()).orElse(0L);
            // 消息app轨迹用于区分订单消息
            if (Objects.nonNull(sendMessage.getAndroidParams()) || Objects.nonNull(sendMessage.getIosParams())) {
                orderId = orderId + 111;
            }
            //-----保存发送记录
            OrderMessageLog orderMessageLog = new OrderMessageLog();
            Long sendUserId = StringUtils.isBlank(sendMessage.getObjectId()) ? 0L : Long.parseLong(sendMessage.getObjectId());
            orderMessageLog.setOrderId(orderId);
            orderMessageLog.setSendUserId(sendUserId);
            orderMessageLog.setGroupId(sendMessage.getRuleId());
            orderMessageLog.setTagName(tag);
            orderMessageLog.setContentIn(JSON.toJSONString(sendMessage));
            orderMessageLog.setContentOut(Optional.ofNullable(serialNumber).orElse("失败"));
            orderMessageLog.setCreateTime(new Date());
            orderLogMessageBService.save(orderMessageLog);
        } catch (Exception ex) {
            log.error(String.format("订单号%s，保存%s发送记录接口异常了:%s", sendMessage.getOrderId(), tag, ex.getMessage()), ex);
            return serialNumber;
        }
        return serialNumber;
    }

    /**
     * 获取工程师设备信息
     *
     * @param masterId
     * @return
     */
    private EngineerDeviceDRO getMeidByMasterId(Integer masterId) {
        ResponseDTO<EngineerDeviceDRO> resp;
        try {
            resp = engineerDeviceListRemoteService.getEngineerDevice(masterId);
            log.info("工程师Id={},获取工程师设备信息- getDeviceByEngineerId 出参{}", masterId, JSON.toJSONString(resp));
        } catch (Exception ex) {
            log.error(String.format("masterId=%s，获取工程师设备信息异常了:%s", masterId, ex.getMessage()), ex);
            return null;
        }
        EngineerDeviceDRO deviceDRO = resp.getData();
        if (!resp.isSuccess() || Objects.isNull(deviceDRO)) {
            return null;
        }
        return deviceDRO;
    }

    /**
     * 获取工程师设备信息-批量
     *
     * @param masterIdList
     * @return
     */
    private List<EngineerDeviceDRO> getMeIdListByMasterIdList(List<Integer> masterIdList) {
        ResponseDTO<List<EngineerDeviceDRO>> resp;
        try {
            resp = engineerDeviceListRemoteService.listEngineerDevice(masterIdList);
            log.info("工程师Id={},获取工程师设备信息- listDeviceByEngineerIdList 出参{}", masterIdList, JSON.toJSONString(resp));
        } catch (Exception ex) {
            log.error(String.format("masterIdList=%s，获取工程师设备信息异常了:%s", masterIdList, ex.getMessage()), ex);
            return null;
        }
        List<EngineerDeviceDRO> deviceDROList = resp.getData();
        if (!resp.isSuccess() || CollectionUtil.isNullOrEmpty(deviceDROList)) {
            return null;
        }
        return deviceDROList;
    }
}
